#ifndef __CHUNK_HH__
#define __CHUNK_HH__
#include "ptypes.h"
#include "drecodec.h"
#include "rabinfp.h"

#include <memory.h>
#include "sfmap.h"
#define MAX_FINGERPRINTS 96

class Chunk {
 
	RabinFP::RabinFingerprint<((1 << 26) + (1 << 15) - 1), 64,64, 0x1F> m_rabin;
	class Packeteer* m_parent;

	public:
	// copy of the buffer
	unsigned char *m_chunk;
	int  m_length;
	int  m_usage;
	unsigned int m_recordNumber;
	unsigned int m_timeStamp;

	// todo - for cross chunk compression
	unsigned int m_nextFlowRecordNumber;
	unsigned int m_prevFlowRecordNumber;
	int m_headerLength;

	ShortFingerprintMap m_map;

	// map of fingerprints into positons
       
	Chunk(class Packeteer *cache) {
	  m_parent = cache;
	  m_chunk=NULL;
	  m_headerLength=40;

	};
	~Chunk() {
	  delete []m_chunk;
	};

	inline bool Populate(unsigned char *packet, int length)  {
	  int i;
	  m_chunk= new unsigned char[length];
	  m_headerLength = 0; // a leftover, delete later
	  
	  if(NULL == m_chunk)
	    return false;
	  
	  //Log("Populate %d bytes\n", length);
	  memcpy(m_chunk, packet, length);
	  m_length = length;
	  // calculate fingerprints here
	  m_rabin.Reset(m_chunk + m_headerLength, length - m_headerLength);
	  
	  for(i = 0;;i++) {
	    int pos;
	    Fingerprint f = m_rabin.NextWinnowedFingerprint(pos);
	    
	    if(pos == -1)
	      break;
	    
	    Log("Populate: adding fp %16llx at position %d\n", f, pos);
	    m_map.AddFingerprint(f, pos);
	  }

	  if (i > MAX_FINGERPRINTS) {
	    printf("limit of %d fps exceeded %d\n", MAX_FINGERPRINTS, i);
	  }

	  return true;
	};

	// really just the first position, for decoding
	inline bool GetFingerprintPosition(Fingerprint fp, short *position) {
	  return m_map.GetFingerprintPosition(fp, position);
	}

	inline void Rewind() {
	  m_map.Rewind();
	}

	inline bool GetNextFingerprint(Fingerprint *fp, short *position){
	  return m_map.GetNextFingerprint(fp, position);
	}

	inline int GetSizeOnDisk() {
	
	  int size = sizeof(int);
	
	  int fprints = MAX_FINGERPRINTS*(sizeof(short) + sizeof(Fingerprint));
	  size += fprints;
	  size += 2*sizeof(uint32_t);
	  size += MAX_CHUNK_SIZE;  
	
	  return size;
	}

	bool Serialize(long handle, class CacheIndex* index, int newRecordNumber);
	bool Deserialize(long handle);
	bool WarmCacheIndex(long handle);
};


#endif
